using BepuPhysics.Collidables;
using BepuPhysics.Constraints;

namespace BepuPhysics.CollisionDetection
{
    public struct PairMaterialProperties
    {
        /// <summary>
        /// 要应用于约束的摩擦系数。最大摩擦力等于法向力乘以摩擦系数。
        /// </summary>
        public float FrictionCoefficient;
        /// <summary>
        /// 沿接触法线的最大相对速度,碰撞约束将在该速度下从穿透中恢复。钳制从弹簧设置创建的速度目标。
        /// </summary>
        public float MaximumRecoveryVelocity;
        /// <summary>
        /// 定义约束的穿透恢复弹簧属性。
        /// </summary>
        public SpringSettings SpringSettings;
    }

    // TODO：我们对回调的使用方式做了一些修改。您应该重新考虑Initialize和Dispose对于此类型是否仍然有意义。
    public unsafe interface INarrowPhaseCallbacks
    {
        /// <summary>
        /// 在构建仿真实例后执行任何所需的初始化逻辑。
        /// </summary>
        /// <param name="Simulation">拥有这些回调的模拟。</param>
        void Initialize(Simulation simulation);

        /// <summary>
        /// 选择是否允许为两个重叠的可碰撞对象继续生成接触。
        /// </summary>
        /// <param name="workerIndex">标识重叠的工作器的索引。</param>
        /// <param name="a">对对中第一个可冲突对象的引用。</param>
        /// <param name="b">对对中第二个可冲突对象的引用。</param>
        /// <return>如果应继续冲突检测,则为True;否则为False。</return>
        bool AllowContactGeneration(int workerIndex, CollidableReference a, CollidableReference b);


        /// <summary>
        /// 提供已为配对创建歧管的通知。提供了更改歧管详细信息的机会。
        /// </summary>
        /// <param name="workerIndex">创建此歧管的工作线程的索引。</param>
        /// <param name="Pair">在其间检测到歧管的一对可碰撞对象。</param>
        /// <param name="歧管">检测到的可碰撞对象之间的接触集。</param>
        /// <param name="pairMaterial">歧管的材料属性。</param>
        /// <return>如果应该为流形创建约束,则为True,否则为False。</return>
        bool ConfigureContactManifold<TManifold>(int workerIndex, CollidablePair pair, ref TManifold manifold, out PairMaterialProperties pairMaterial) where TManifold : struct, IContactManifold<TManifold>;

        // TODO：每个孩子和每个联系人都有一个关于更细粒度材料调优的论点。在我们承诺之前需要一个有效的方法来做这件事-
        // 一种可能性是每个凸流形都有一种材质。对于非凸流形,每个接触都有一个材料属性。
        // 这不是一个理想的设置-求解器中的每个触点需要额外的16-20个字节,这是相当痛苦的。

        /// <summary>
        /// 选择是否允许为复合(包括)对中两个重叠的可碰撞对象的子项继续生成接触。
        /// </summary>
        /// <param name="Pair">两个子冲突项的父对。</param>
        /// <param name="Child IndexA">对中可碰撞A的子项的索引。如果可碰撞A不是复合的,则该值始终为0。</param>
        /// <param name="Child IndexB">对中可碰撞B的子项的索引。如果可碰撞B不是复合的,则该值始终为0。</param>
        /// <return>如果应继续冲突检测,则为True;否则为False。</return>
        /// <remarks>This is called for each sub-overlap in a collidable pair involving compound collidables. If neither collidable in a pair is compound, this will not be called.
        /// 对于包含复合的对,如果前面对AllowContactGeneration的调用为拥有对返回false,则不会调用此函数。请注意,有可能
        /// 如果同一子对启用了连续冲突检测,则该函数将被调用两次;
        /// 在触点生成测试之前运行的CCD扫描测试在执行子对测试之前也会询问。</MARKEMS>
        bool AllowContactGeneration(int workerIndex, CollidablePair pair, int childIndexA, int childIndexB);
        /// <summary>
        /// 提供已在复合(包括)对中的两个可碰撞对象的子项之间创建流形的通知。
        /// 提供了更改歧管详细信息的机会。
        /// </summary>
        /// <param name="workerIndex">创建此歧管的工作线程的索引。</param>
        /// <param name="Pair">在其间检测到歧管的一对可碰撞对象。</param>
        /// <param name="Child IndexA">对中可碰撞A的子项的索引。如果可碰撞A不是复合的,则该值始终为0。</param>
        /// <param name="Child IndexB">对中可碰撞B的子项的索引。如果可碰撞B不是复合的,则该值始终为0。</param>
        /// <param name="歧管">检测到的可碰撞对象之间的接触集。</param>
        /// <return>如果应将此流形考虑用于约束生成,则为True,否则为False。</return>
        bool ConfigureContactManifold(int workerIndex, CollidablePair pair, int childIndexA, int childIndexB, ref ConvexContactManifold manifold);

        /// <summary>
        /// 释放回调持有的所有资源。在处理它时由拥有的窄阶段调用。
        /// </summary>
        void Dispose();
    }
}
